"""Export service for conversations."""

import json
import io
from typing import Optional, Tuple, AsyncGenerator
from datetime import datetime
import motor.motor_asyncio
from bson import ObjectId

from ..models.conversation_model import Conversation, Message


class ExportService:
    """Handles conversation export in various formats."""
    
    def __init__(self, mongodb_client: motor.motor_asyncio.AsyncIOMotorClient):
        """Initialize export service.
        
        Args:
            mongodb_client: MongoDB client instance
        """
        self.mongodb = mongodb_client
        self.db = mongodb_client.ai_writing
        self.conversations = self.db.conversations
    
    async def export_json(
        self,
        conversation_id: str,
        user_id: str
    ) -> Tuple[AsyncGenerator[bytes, None], str]:
        """Export conversation as JSON.
        
        Args:
            conversation_id: Conversation ID
            user_id: User ID for ownership verification
            
        Returns:
            Tuple of (content generator, filename)
        """
        # Get conversation
        doc = await self.conversations.find_one({
            "_id": ObjectId(conversation_id),
            "user_id": user_id
        })
        
        if not doc:
            raise ValueError("Conversation not found")
        
        conversation = Conversation.from_dict(doc)
        
        # Prepare export data
        export_data = {
            "export_version": "1.0",
            "export_date": datetime.utcnow().isoformat(),
            "conversation": {
                "id": str(conversation._id),
                "title": conversation.title,
                "created_at": conversation.created_at.isoformat(),
                "updated_at": conversation.updated_at.isoformat(),
                "tags": conversation.tags,
                "category": conversation.category.value,
                "model_preference": conversation.model_preference,
                "settings": conversation.settings.to_dict(),
                "statistics": conversation.statistics.to_dict(),
                "messages": [
                    {
                        "id": msg.id,
                        "role": msg.role.value,
                        "content": msg.content,
                        "timestamp": msg.timestamp.isoformat(),
                        "model": msg.model,
                        "tokens_used": msg.tokens_used,
                        "cost": msg.cost,
                        "metadata": msg.metadata.to_dict()
                    }
                    for msg in conversation.messages
                ]
            }
        }
        
        # Convert to JSON bytes
        json_str = json.dumps(export_data, ensure_ascii=False, indent=2)
        
        async def generate():
            yield json_str.encode('utf-8')
        
        # Generate filename
        safe_title = "".join(c for c in conversation.title if c.isalnum() or c in (' ', '-', '_'))[:50]
        filename = f"{safe_title}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
        
        return generate(), filename
    
    async def export_markdown(
        self,
        conversation_id: str,
        user_id: str
    ) -> Tuple[AsyncGenerator[bytes, None], str]:
        """Export conversation as Markdown.
        
        Args:
            conversation_id: Conversation ID
            user_id: User ID for ownership verification
            
        Returns:
            Tuple of (content generator, filename)
        """
        # Get conversation
        doc = await self.conversations.find_one({
            "_id": ObjectId(conversation_id),
            "user_id": user_id
        })
        
        if not doc:
            raise ValueError("Conversation not found")
        
        conversation = Conversation.from_dict(doc)
        
        # Build Markdown content
        lines = []
        
        # Header
        lines.append(f"# {conversation.title}")
        lines.append("")
        
        # Metadata
        lines.append("## Metadata")
        lines.append(f"- **Created**: {conversation.created_at.strftime('%Y-%m-%d %H:%M:%S UTC')}")
        lines.append(f"- **Updated**: {conversation.updated_at.strftime('%Y-%m-%d %H:%M:%S UTC')}")
        lines.append(f"- **Category**: {conversation.category.value}")
        lines.append(f"- **Model**: {conversation.model_preference}")
        if conversation.tags:
            lines.append(f"- **Tags**: {', '.join(conversation.tags)}")
        lines.append("")
        
        # Statistics
        lines.append("## Statistics")
        lines.append(f"- **Total Messages**: {conversation.statistics.total_messages}")
        lines.append(f"- **Total Tokens**: {conversation.statistics.total_tokens:,}")
        lines.append(f"- **Total Cost**: ${conversation.statistics.total_cost:.4f}")
        lines.append("")
        
        # Messages
        lines.append("## Conversation")
        lines.append("")
        
        for msg in conversation.messages:
            # Message header
            timestamp = msg.timestamp.strftime('%H:%M:%S')
            
            if msg.role.value == "user":
                lines.append(f"### User [{timestamp}]")
            elif msg.role.value == "assistant":
                model_info = f" ({msg.model})" if msg.model else ""
                lines.append(f"### Assistant{model_info} [{timestamp}]")
            else:  # system
                lines.append(f"### System [{timestamp}]")
            
            lines.append("")
            
            # Message content
            lines.append(msg.content)
            lines.append("")
            
            # Message metadata
            if msg.tokens_used > 0:
                lines.append(f"*Tokens: {msg.tokens_used:,} | Cost: ${msg.cost:.4f}*")
                lines.append("")
            
            if msg.metadata.edited:
                lines.append("*This message was edited*")
                lines.append("")
        
        # Footer
        lines.append("---")
        lines.append(f"*Exported on {datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S UTC')}*")
        
        # Convert to bytes
        markdown_content = "\n".join(lines)
        
        async def generate():
            yield markdown_content.encode('utf-8')
        
        # Generate filename
        safe_title = "".join(c for c in conversation.title if c.isalnum() or c in (' ', '-', '_'))[:50]
        filename = f"{safe_title}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.md"
        
        return generate(), filename
    
    async def export_to_dict(self, conversation_id: str, user_id: str) -> dict:
        """Export conversation as dictionary (for internal use).
        
        Args:
            conversation_id: Conversation ID
            user_id: User ID for ownership verification
            
        Returns:
            Conversation data as dictionary
        """
        doc = await self.conversations.find_one({
            "_id": ObjectId(conversation_id),
            "user_id": user_id
        })
        
        if not doc:
            raise ValueError("Conversation not found")
        
        conversation = Conversation.from_dict(doc)
        return conversation.to_dict()